package sundun.sharding.utils;

import lombok.extern.slf4j.Slf4j;
import sundun.sharding.constant.ShardingConstant;
import sundun.sharding.enums.ShardingRuleEnum;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.Optional;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *  TimeFrameEndpointUtil
 * 时间范围工具类
 * @author zxl
 * @date 2024/08/02 14:03
 */
@Slf4j
public class TimeFrameEndpointUtil {



    /**
     * 获取月最小分片值
     * @param tableNames 表名集合   格式：（ims_yesterday_jqxx_202301）
     * @return 最小分片值
     */
    public static String getLowerEndpointMonth(Collection<String> tableNames) {
        Optional<LocalDateTime> optional = tableNames.stream()
                .map(o -> LocalDateTime.parse(o.replace(ShardingConstant.TABLE_SPLIT_SYMBOL, "") + "01 00:00:00", ShardingConstant.DATE_TIME_FORMATTER))
                .min(Comparator.comparing(Function.identity()));
        if (optional.isPresent()) {
            ZonedDateTime zonedDateTime = optional.get().atZone(ZoneId.systemDefault());
            Instant instant = zonedDateTime.toInstant();
            return String.valueOf(Date.from(instant));
        } else {
            log.error(">>>>>>>>>> 【ERROR】获取数据最小分表失败，请稍后重试，tableName：{}", tableNames);
            throw new IllegalArgumentException("获取数据最小分表失败，请稍后重试");
        }
    }


    /**
     * 获取月最大分片值
     * @param tableNames 表名集合 格式：（ims_yesterday_jqxx_202301）
     * @return 最大分片值
     */
    public String getUpperEndpointMonth(Collection<String> tableNames) {
        Optional<LocalDateTime> optional = tableNames.stream()
                .map(o -> LocalDateTime.parse(o.replace(ShardingConstant.TABLE_SPLIT_SYMBOL, "") + "01 00:00:00", ShardingConstant.DATE_TIME_FORMATTER))
                .max(Comparator.comparing(Function.identity()));
        if (optional.isPresent()) {
            ZonedDateTime zonedDateTime = optional.get().atZone(ZoneId.systemDefault());
            Instant instant = zonedDateTime.toInstant();
            return String.valueOf(Date.from(instant));
        } else {
            log.error(">>>>>>>>>> 【ERROR】获取数据最大分表失败，请稍后重试，tableName：{}", tableNames);
            throw new IllegalArgumentException("获取数据最大分表失败，请稍后重试");
        }
    }


    /**
     * 获取年最小分片值
     * @param tableNames 表名集合 格式：（ims_yesterday_jqxx_2023_0）
     * @param logicTableName 逻辑表
     * @return 最小分片值
     */
    public static String getLowerEndpointYear(Collection<String> tableNames,String logicTableName) {
        Optional<String> optional = tableNames.stream()
                .map(o -> {
                    Pattern pattern = Pattern.compile(String.format(ShardingRuleEnum.YEAR.getMatching(), logicTableName+ ShardingConstant.TABLE_SPLIT_SYMBOL));
                    Matcher matcher = pattern.matcher(o);
                    if (matcher.matches()){
                        String year = matcher.group(1);
                        return year;
                    }
                    return null;
                }).filter(s ->s != null)
                .min(Comparator.comparing(Function.identity()));
        if (optional.isPresent()) {
            return optional.get();
        } else {
            log.error(">>>>>>>>>> 【ERROR】获取数据最小分表失败，请稍后重试，tableName：{}", tableNames);
            throw new IllegalArgumentException("获取数据最小分表失败，请稍后重试");
        }
    }


    /**
     * 获取年最大分片值
     * @param tableNames 表名集合 格式：（ims_yesterday_jqxx_2023_0）
     * @return 最大分片值
     */
    public static String getUpperEndpointYear(Collection<String> tableNames,String logicTableName) {
        Optional<String> optional = tableNames.stream()
                .map(o -> {
                    Pattern pattern = Pattern.compile(String.format(ShardingRuleEnum.YEAR.getMatching(), logicTableName+ ShardingConstant.TABLE_SPLIT_SYMBOL));
                    Matcher matcher = pattern.matcher(o);
                    if (matcher.matches()){
                        String year = matcher.group(1);
                        return year;
                    }
                    return null;
                }).filter(s ->s != null)
                .max(Comparator.comparing(Function.identity()));
        if (optional.isPresent()) {
            return optional.get();
        } else {
            log.error(">>>>>>>>>> 【ERROR】获取数据最小分表失败，请稍后重试，tableName：{}", tableNames);
            throw new IllegalArgumentException("获取数据最小分表失败，请稍后重试");
        }
    }
}
